﻿using System;
using System.Collections;
using System.Collections.Generic;

namespace winS.Unity
{
    /// <summary>
    /// 协程组.
    /// 提供对协程的统一管理
    /// </summary>
    public class CoroutineGroup
    {
        public int count => coroutineList.Count;

        private bool stopping;

        private readonly List<Coroutine> coroutineList = new List<Coroutine>();

        /// <summary>
        /// 停止所有在当前协程组下运行的协程
        /// </summary>
        public void Stop()
        {
            stopping = true;
            foreach (var coroutine in coroutineList) coroutine.Stop();
            stopping = false;
            coroutineList.Clear();
        }
        /// <summary>
        /// 添加 <paramref name="coroutine"/> 到协程组中
        /// </summary>
        public void Add(Coroutine coroutine)
        {
            if (!coroutine.running) return;
            if (coroutineList.Contains(coroutine)) return;
            coroutine.onFinished += () =>
            {
                if (stopping) return;
                coroutineList.Remove(coroutine);
            };
            coroutineList.Add(coroutine);
        }
        /// <summary>
        /// 清除当前组下所有协程
        /// </summary>
        /// <param name="stop">在清除的同时停止这些协程</param>
        public void Clear(bool stop = true)
        {
            if (stop) Stop();
            else coroutineList.Clear();
        }
        /// <summary>
        /// 在当前协程组下启动一个协程 <paramref name="enumerator"/>
        /// </summary>
        public Coroutine Start(IEnumerator enumerator) => StartWithName(enumerator, null);
        /// <summary>
        /// 在当前协程组下启动带有 <see cref="IEnumerator"/> 返回值的协程函数
        /// </summary>
        public Coroutine Start(Func<IEnumerator> enumeratorFunction) => Start(enumeratorFunction());

        public Coroutine StartWithName(IEnumerator enumerator, string name)
        {
            CoroutineCore coroutineCore = CoroutineCorePool.Pop(enumerator);
            coroutineCore.name = name;
            Coroutine coroutine = new Coroutine(coroutineCore);
            coroutine.onFinished += () =>
            {
                if (stopping) return;
                coroutineList.Remove(coroutine);
            };
            //先加入列表再添加到启动器中
            //协程可能在自身运行时调用 CoroutineGroup.Stop
            //如果先启动再加入列表可能导致无法通过 CoroutineGroup.Stop 来停止
            coroutineList.Add(coroutine);
            CoroutineStarter.Add(coroutineCore);
            return coroutine;
        }
    }
}